Skip to content

feat(opencode): TokenPilot adapter for OpenCode - #96

Merged
Xubqpanda merged 3 commits into
zjunlp:mainfrom
boxabirds:claude/upstream-6-opencode-adapter
Oct 2, 2026
Merged

Xubqpanda merged 3 commits into
zjunlp:mainfrom
boxabirds:claude/upstream-6-opencode-adapter

Conversation

@boxabirds

Copy link
Copy Markdown

Summary

Closes #93. Adds TokenPilot support for OpenCode, verified on 1.18.33. It builds on the shared eviction core from #95.

Measured benefit

The test used llama-server with Qwen3-1.7B and a 32k context window, running the same scripted coding session with the adapter off and on, from a cold cache.

Adapter off Adapter on
Prompt tokens processed 71,273 9,612 (−87%)
Wall time 1,887 s 222 s
Context overflows 1 0

lightrsi opencode doctor reported healthy after the run.

How it plugs in

OpenCode loads plugins in-process, so no proxy is needed.

TokenPilot feature OpenCode hook
Stable prefix experimental.chat.system.transform
Reduction experimental.chat.messages.transform, which runs before every model step
Recovery the shared recovery MCP server, registered in opencode.json
Eviction (opt-in, off by default) messages.transform, plus a stored per-session overlay. OpenCode has no lasting part-edit hook, so evictions are re-applied identically on every request.

Install is reversible. It adds one plugin loader file and exactly one mcp key to opencode.json, with a backup. It never rewrites an opencode.jsonc. Uninstall removes only what install added. The adapter is also registered in the shared CLI as lightrsi opencode status|report|doctor|visual|mode|….

What's in the 3 commits

Area Lines
OpenCode adapter (components/adapters/opencode/src) ~1,400
Shared code for in-process adapters (components/adapters/shared/canonical/) ~1,500
Tests ~2,470
CLI registration ~200
Docs (README, design note, HOSTS.md, website page) ~390
Lockfile and CI step ~45

The shared code sits on #95's eviction core. It handles config, the before-call pipeline, reduction and eviction for hosts that hand over the whole transcript. It also applies the repeat-read rule from #92: a file read stays trimmed while the same read is still in the history.

Known limits (OpenCode 1.18.33)

  • hooks.dynamicContextTarget=user runs as developer, because messages.transform runs before system.transform. doctor reports this.
  • The v2 plugin API isn't used, because it has no message, tool or session hooks yet.
  • There are no in-host slash commands; use the shared CLI instead.
  • The Context Cleaner isn't integrated yet.

Tests

  • OpenCode adapter: 189 tests. They cover the message codec, the overlay, the runtime hooks, install and uninstall, doctor and config.
  • Shared code: one test file per module, each listing the cases it covers. Four mutation checks each make the expected tests fail.
  • CLI: 108 tests.
  • pnpm build, pnpm typecheck and check:boundaries pass, and every suite CI runs passes.

Prepared with help from Claude Code; the commits are marked Co-Authored-By: Claude.

claude added 3 commits October 1, 2026 01:35
Adds an in-process OpenCode v1 server plugin (`components/adapters/opencode`)
plus the host glue it uses (`components/adapters/shared/canonical`), built on the
shared packages and mirroring the Claude Code adapter. Refs zjunlp#93.

- Stabilizer: `experimental.chat.system.transform` (developer target; the user
  target is not possible in 1.18.33 because messages are transformed first).
- Reduction: request-time in `experimental.chat.messages.transform`, through
  the shared `@lightrsi/reduction` pipeline over a canonical envelope.
- Recovery: the shared recovery MCP server, registered in `opencode.json`.
- Eviction (opt-in, needs taskStateEstimator settings): the shared
  canonical-surface cycle, applied as a durable per-session overlay.
- Repeat-read rule: as in zjunlp#92, a disclosed path is carried into the next
  request only when the trimmed read that disclosed it has left the history;
  the record is saved per session so restarts keep it.
- Reversible install with backups (jsonc configs are printed, never
  rewritten); never writes credentials; every hook fails open and logs to
  `<stateDir>/tokenpilot/adapter.log`.

Tests: 189 in the package. The shared glue (config, reduction, memo store,
before-call, eviction, logger) has one test file per module, each listing the
cases it covers; plus runtime, codec/overlay, install/doctor and registration
tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S6it2Si8k8XNGMF8RdyMQz
`lightrsi opencode status|report|doctor|visual|mode|stabilizer|reduction|eviction`
through a small in-process host bridge (hosts/in-process.ts) that reuses the
restricted host command handler, so OpenCode gets the same command surface as
Claude Code. TOKENPILOT_OPENCODE_CONFIG / TOKENPILOT_OPENCODE_CONFIG_DIR select
non-default config locations.

Tests: tests/in-process-hosts.test.ts (registration, every command, env
overrides).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S6it2Si8k8XNGMF8RdyMQz
- components/adapters/opencode/README.md is in the adapter commit; this adds
  the design note (docs/adapters/opencode-design.md), the HOSTS.md and
  adapters README rows, the website host page and compatibility matrix, and
  the sidebar link.
- CI runs the OpenCode adapter suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S6it2Si8k8XNGMF8RdyMQz
@Xubqpanda
Xubqpanda merged commit bcbf88d into zjunlp:main Oct 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integrate OpenCode into LightRSI

3 participants